#pragma once
#include "lib.h"

class QueryResult;
class TextQuery
{
public:
	using line_no = vector<string>::size_type;
	TextQuery() {};
	TextQuery(ifstream &infile) : lpLinesVec(new vector<string>) {
		loadFile(infile);
	}
	~TextQuery() {}

	void loadFile(ifstream &);
	QueryResult query(const string &) const;

private:
	shared_ptr<vector<string>> lpLinesVec;
	map<string, shared_ptr<set<line_no>>> wordRowsMap;
};

class QueryResult
{
	friend ostream& operator<<(ostream &, const QueryResult&);
public:
	QueryResult() = default;
	QueryResult(string s, shared_ptr<set<TextQuery::line_no>> rows, shared_ptr<vector<string>> lines) :
		sought(s), lpWordRowsSet(rows), lpLinesVec(lines) {}
	~QueryResult() = default;

	set<TextQuery::line_no>::iterator begin() {
		return lpWordRowsSet->begin();
	}
	set<TextQuery::line_no>::iterator end() {
		return lpWordRowsSet->end();
	}
	const shared_ptr<vector<string>> get_file() const {
		return lpLinesVec;
	}
private:
	string sought;
	shared_ptr<set<TextQuery::line_no>> lpWordRowsSet;
	shared_ptr<vector<string>> lpLinesVec;
};

inline
ostream& operator<<(ostream &os, const QueryResult &qr) {
	TextQuery::line_no times = qr.lpWordRowsSet->size();
	os << "element occurs " << times << " " << (times == 1 ? "time" : "times") << endl;
	for (auto num : *qr.lpWordRowsSet) {
		os << "(line " << num << ") " << *(qr.lpLinesVec->begin() + num) << endl;
	}
	return os;
}